/*
 * Copyright (C) 2014
 *
 * Brick Yang <printfxxx@163.com>
 *
 * This program is free software. You can redistribute it and/or
 * modify it as you like.
 */

/**
 * @file	proto.h
 * @brief	Header file for communication protocol
 */

#ifndef _PROTO_H_
#define _PROTO_H_

#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/socket.h>
#else
#include <stdbool.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif

#define PROTO_IDENTIFY_0	0xaa
#define PROTO_IDENTIFY_1	0x55

enum {
	MAGIC_WORKER = 0,
	MAGIC_NETDEV,
	MAGIC_MAX,
	MAGIC_MSG = 0xf0,
#define MSG_ID_STDOUT	0
#define MSG_ID_STDERR	1
	MAGIC_RESP,
	MAGIC_RET_CODE,
	MAGIC_PRIV
};

enum {
	WORKER_ID_WORKER = 0,
	WORKER_ID_FC,
	WORKER_ID_QUEUE,
	WORKER_ID_POOL_SZ,
	WORKER_ID_PKT_CNT,
	WORKER_ID_ADD_PKT,
	WORKER_ID_DEL_PKT,
	WORKER_ID_PKT_TXQ,
	WORKER_ID_DUMP_PKT,
	WORKER_ID_MAX
};

enum {
	NETDEV_ID_NETDEV,
	NETDEV_ID_PAUSE,
#define NETDEV_PAUSE_OPT_AUTONEG	0
#define NETDEV_PAUSE_OPT_RX		1
#define NETDEV_PAUSE_OPT_TX		2
	NETDEV_ID_LINK,
#define NETDEV_LINK_OPT_AUTONEG		0
#define NETDEV_LINK_OPT_DUPLEX		1
#define NETDEV_LINK_OPT_SPEED		2
#define NETDEV_LINK_OPT_ADVSET		3
#define NETDEV_LINK_OPT_ADVCLR		4
	NETDEV_ID_START,
	NETDEV_ID_STOP,
	NETDEV_ID_CLEAR,
	NETDEV_ID_STATS,
	NETDEV_ID_ATTACH,
	NETDEV_ID_DETACH,
	NETDEV_ID_RXDUMP,
	NETDEV_ID_DEVSTATS,
	NETDEV_ID_IOCTL,
	NETDEV_ID_MAX
};

#ifdef __KERNEL__
typedef struct socket *proto_sock_t;
typedef struct kvec proto_iovec_t;
#else
typedef int proto_sock_t;
typedef struct iovec proto_iovec_t;
#endif

typedef struct proto_hdr {
	__u8	magic;
	__u8	id;
	__u16	length;
} proto_hdr_t;

typedef struct proto_txd {
	proto_hdr_t	hdr;
	struct {
#define PROTO_IOVEC_MAX		8
		proto_iovec_t	head_iov[2];
		proto_iovec_t	iov[PROTO_IOVEC_MAX];
	};
	size_t		num;
} proto_txd_t;

typedef struct proto_rxd {
	proto_hdr_t	hdr;
#define PROTO_BUF_MAX	65536
	void		*buf;
	size_t		len;
} proto_rxd_t;

typedef struct proto_handle {
	bool		io_err;
	proto_sock_t	sock;
	ssize_t (*sendmsg)(proto_sock_t sock, proto_iovec_t *iov, size_t num, int flags);
	ssize_t (*recv)(proto_sock_t sock, void *buf, size_t len, int flags);
} proto_handle_t;

int proto_send(proto_handle_t *handle, proto_txd_t *txd);
int proto_recv(proto_handle_t *handle, proto_rxd_t *rxd);
int proto_send_ret_code(proto_handle_t *handle, int ret);
int proto_get_u8(void **buf, size_t *len, __u8 *out);
int proto_get_u16(void **buf, size_t *len, __u16 *out);
int proto_get_u32(void **buf, size_t *len, __u32 *out);
int proto_get_u64(void **buf, size_t *len, __u64 *out);
char *proto_get_str(void **buf, size_t *len);
void *proto_get_buf(void **buf, size_t *len, size_t sz);

#endif	/* _PROTO_H_ */
